<script setup lang="ts">
import Message from '@arco-design/web-vue/es/message'
import type { RequestOption } from '@arco-design/web-vue/es/upload'
import { FileApi } from '@/apis'

const props = withDefaults(defineProps<Props>(), {
  modelValue: '',
  width: 90,
  height: 110,
  isEdit: true,
  type: 'picture',
})

const emits = defineEmits(['update:modelValue'])

interface Props {
  modelValue: string | null
  width?: number
  height?: number
  isEdit?: boolean
  type?: 'button' | 'picture'
}

const imgWidth = computed(() => `${props.width}px`)
const imgHeight = computed(() => `${props.height}px`)

const file = ref()

const visible = ref(false)
const current = ref(0)
const onPreview = () => {
  visible.value = true
}

const onProgress = (currentFile) => {
  file.value = currentFile
}

const successHandle = (fileItem) => {
  file.value = fileItem
  emits('update:modelValue', fileItem.response.url)
}

const deleteImage = () => {
  file.value = null
}

// 上传
const handleUpload = (options: RequestOption) => {
  const controller = new AbortController();
  (async function requestWrap() {
    const { onProgress, onError, onSuccess, fileItem, name = 'file' } = options
    onProgress(20)
    const formData = new FormData()
    formData.append(name as string, fileItem.file as Blob)
    try {
      const res = await FileApi.upload(formData)
      Message.success('上传成功')
      onSuccess(res)
    } catch (error) {
      onError(error)
    }
  })()
  return {
    abort() {
      controller.abort()
    },
  }
}

watch(() => props.modelValue, (val) => {
  file.value = { url: val || '' }
}, { immediate: true })
</script>

<template>
  <a-upload
    v-if="props.isEdit"
    action="/" :file-list="file ? [file] : []" image-preview :show-file-list="false" :custom-request="handleUpload"
    @success="successHandle" @progress="onProgress"
  >
    <template #upload-button>
      <div
        :class="`arco-upload-list-item${file && file.status === 'error' ? ' arco-upload-list-item-error' : ''
        }`"
      >
        <div v-if="file && file.url" class="arco-upload-list-picture custom-upload-avatar">
          <img :src="file.url">
          <div class="arco-upload-list-picture-mask center">
            <a-space size="medium">
              <icon-eye @click.stop="onPreview" />
              <icon-delete @click.stop="deleteImage" />
            </a-space>
          </div>
          <a-progress
            v-if="file.status === 'uploading' && file.percent < 100" :percent="file.percent" type="circle"
            size="mini" :style="{
              position: 'absolute',
              left: '50%',
              top: '50%',
              transform: 'translateX(-50%) translateY(-50%)',
            }"
          />
        </div>
        <div v-else>
          <div v-if="props.type === 'picture'" class="arco-upload-picture-card">
            <div class="arco-upload-picture-card-text">
              <IconPlus />
              <div style="margin-top: 10px; font-weight: 600">
                Upload
              </div>
            </div>
          </div>
          <a-button v-else type="primary">
            <icon-upload />
            上传图片
          </a-button>
        </div>
      </div>
    </template>
  </a-upload>
  <a-image
    v-if="!props.isEdit"
    :width="props.width" :height="props.height"
    :src="file ? file.url : ''"
  />
  <a-image-preview-group v-if="file" v-model:visible="visible" v-model:current="current" infinite :src-list="[file.url]" />
</template>

<style lang="less" scoped>
:deep(.arco-upload-picture-card),
:deep(.arco-upload-list-picture) {
  min-width: auto;
  width: v-bind(imgWidth);
  height: v-bind(imgHeight);
  margin: 0;
}
:deep(.arco-upload-list-item) {
  margin-top: 0;
}

.center {
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: center;
}
</style>
